﻿using System;

namespace TrekBattle
{
    class Program
    {
        // Command line arguement positions
        const int SEED_VALUE = 0;
        const int FIRST_FILENAME = 1;
        const int SECOND_FILENAME = 2;

        // Number of accepted arguements
        const int NUMBER_OF_ARGUEMENTS = 3;

        private static Random Rand;

        private static Fleet Fleet1;
        private static Fleet Fleet2;

        private static int round = 0;

        static void Main(string[] args)
        {
            if (args.Length != NUMBER_OF_ARGUEMENTS)
                EndProgram("Invalid number of command line arguements entered");

            try
            {
                int seed = Convert.ToInt32(args[SEED_VALUE]);
                if (seed < 0)
                    throw new System.ArgumentException();
                Rand = new Random(seed);
            }
            catch (Exception ex)
            {
                if (ex is System.OverflowException  ||
                    ex is System.FormatException    ||
                    ex is System.ArgumentException)
                    EndProgram("Invalid seed value entered");
                else
                    throw;
            }

            Setup(args[FIRST_FILENAME], args[SECOND_FILENAME]);

            while (Fleet1.HasShipsAlive() && Fleet2.HasShipsAlive())
                NextRound();

            DisplayFinalReport();
        }

        public static void Setup(string filename1, string filename2)
        {
            Fleet1 = new Fleet(filename1);
            Fleet2 = new Fleet(filename2);
        }

        private static void NextRound()
        {
            round++;

            Attack(Fleet1, Fleet2);
            Attack(Fleet2, Fleet1);

            Fleet1.RemoveDestroyedShips();
            Fleet2.RemoveDestroyedShips();

            RechargeShields(Fleet1);
            RechargeShields(Fleet2);

            Fleet1.DisplayRoundReport(round);
            Fleet2.DisplayRoundReport(round);
        }

        private static void Attack(Fleet fleet, Fleet enemies)
        {
            foreach (Ship ship in fleet.GetShips())
            {
                int damage = ship.GetWeaponBaseDamage() + Rand.Next(ship.GetWeaponRandomDamage());
                Ship target = enemies.GetShip(Rand.Next(enemies.ShipCount())); 

                target.Hit(damage);
            }
        }

        private static void RechargeShields(Fleet fleet)
        {
            foreach (Ship ship in fleet.GetShips())
                ship.RechargeShield();
        }

        private static void DisplayFinalReport()
        {
            Fleet survivingFleet = null;
            Fleet destroyedFleet = null;
            if (Fleet1.HasShipsAlive())
            {
                survivingFleet = Fleet1;
                destroyedFleet = Fleet2;
            }
            else if (Fleet2.HasShipsAlive())
            {
                survivingFleet = Fleet2;
                destroyedFleet = Fleet1;
            }

            if (survivingFleet == null)
                Console.WriteLine("After round " + round.ToString() + " both fleets were destroyed");
            else
            {
                Console.WriteLine("After round " + round.ToString() + " the " + survivingFleet.GetName() + " has won");
                Console.WriteLine("  " + destroyedFleet.ShipsLostCount().ToString() + " enemy ships destroyed");
                Console.WriteLine("  " + survivingFleet.ShipsLostCount().ToString() + " ships lost");
                Console.WriteLine("  " + survivingFleet.ShipCount().ToString() + " ships survived");
                survivingFleet.DisplayDamageReport();

            }
        }

        private static void EndProgram(string errorText)
        {
            Console.WriteLine("Program failed with the following error");
            Console.WriteLine(errorText);
            Environment.Exit(0);
        }
    }
}